package com.googlecode.spreadit.handler;

import java.util.List;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.AndroidRuntimeException;
import android.util.Log;

import com.googlecode.spreadit.bean.Message;
import com.googlecode.spreadit.bean.SpreadReceiver;
import com.googlecode.spreadit.bean.SpreadRule;
import com.googlecode.spreadit.matching.SpreadRuleBase;

/**
 * Central handler component. It is called by the different receivers, checks
 * the {@link Message}s against the {@link SpreadRuleBase} and dispatches the
 * messages according to the {@link SpradRules}.
 * 
 * @see OutgoingSmsHandler
 * @see OutgoingEmailHandler
 * @see OutgoingWhatsAppHandler
 * 
 * @author Markus L. Dechert (markus.dechert@googlemail.com)
 */
public class SpreadRuleHandler {

	private final String LOG_TAG = getClass().getSimpleName();

	private static SpreadRuleHandler singletonInstance;

	/**
	 * Key for the content in the {@link Intent#getExtras() extra bundle} in the
	 * {@link Intent} that is issued in order to call the respective
	 * <tt>Outgoing*Handler</tt>.
	 */
	public static final String EXTRAS_CONTENT_KEY = "content";

	/**
	 * Key for the {@link Message} payload in the intent to one of the
	 * <tt>Outgoing*Handler</tt>s.
	 */
	public static final String MESSAGE_BUNDLE_KEY = "message";

	/**
	 * Key for the {@link SpreadReceiver} payload in the intent to one of the
	 * <tt>Outgoing*Handler</tt>s.
	 */
	public static final String RECEIVER_BUNDLE_KEY = "receiver";

	/**
	 * Method to return the singleton instance of this class.
	 * 
	 * @return singleton instance.
	 */
	public static SpreadRuleHandler getInstance() {
		if (singletonInstance == null) {
			singletonInstance = new SpreadRuleHandler();
		}
		return singletonInstance;
	}

	/**
	 * Instantiate via {@link #getInstance()}.
	 */
	private SpreadRuleHandler() {
	}

	/**
	 * This method browses the {@link SpreadRuleBase} and obtains the matching
	 * rules. For each matching rule the message is forwarded accordingly.
	 * 
	 * @param context
	 *            of the calling Android component.
	 * @param m
	 *            the message to forward.
	 */
	public void matchAndSpread(Context context, Message m) {
		Log.d(LOG_TAG, "SpreadRuleHandler.matchAndSpread called.");

		SpreadRuleBase srb = SpreadRuleBase.getInstance();
		List<SpreadRule> matchingRules = srb.browseForMatches(m);

		Log.d(LOG_TAG, "Found " + matchingRules.size()
				+ " matching rules. Spreading messages...");

		for (SpreadRule r : matchingRules) {
			spreadMessage(context, m, r);
		}
	}

	/**
	 * Dispatch the message according to the
	 * {@link SpreadRule#getTargetChannel() rule channel}.
	 * 
	 * @param message
	 *            the {@link Message} to spread/dispatch
	 * @param rule
	 *            the {@link SpreadRule} that matched and that defines the
	 *            targets that that message should be spreaded to
	 */
	public void spreadMessage(Context context, Message message, SpreadRule rule) {
		// Wrap up message and rule into a bundle
		Bundle messageBundle = new Bundle();
		messageBundle.putSerializable(EXTRAS_CONTENT_KEY, message);

		for (SpreadReceiver rec : rule.getTargetReceivers()) {
			Intent i = null;

			Bundle receiverBundle = new Bundle();
			receiverBundle.putSerializable(EXTRAS_CONTENT_KEY, rec);

			// Create Intent for the right handler
			switch (rec.getTargetChannel()) {
			case SMS:
				Log.v(LOG_TAG, "Calling OutgoingSmsHandler...");
				i = new Intent(OutgoingSmsHandler.HANDLER_ID);
				break;
			case EMAIL:
				Log.v(LOG_TAG, "Calling OutgoingEmailHandler...");
				i = new Intent(OutgoingEmailHandler.HANDLER_ID);
				break;
			case WHATSAPP:
				Log.v(LOG_TAG, "Calling OutgoingWhatsAppHandler...");
				i = new Intent(OutgoingWhatsAppHandler.HANDLER_ID);
				break;
			default:
				throw new AndroidRuntimeException(
						"No outgoing handler found for channel ["
								+ rec.getTargetChannel() + "].");
			}

			i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

			i.putExtra(MESSAGE_BUNDLE_KEY, messageBundle);
			i.putExtra(RECEIVER_BUNDLE_KEY, receiverBundle);

			context.startActivity(i);
		}
	}
}
